<?php

namespace App\Models\Order;

use App\Models\Attachment;
use App\Models\Customer;
use App\Models\User;
use Carbon\Carbon;
use Hyn\Tenancy\Traits\UsesTenantConnection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * App\Models\Order\Order
 *
 * @property int $id
 * @property int $customer_id
 * @property string $order_number
 * @property string|null $description
 * @property string $expected_rental_out_date 预期借出日期
 * @property string|null $real_rental_out_date 实际借出日期
 * @property string $expected_return_date 预期归还日期
 * @property string|null $real_return_date 实际归还时间
 * @property string|null $expected_ship_date 预期物流送出时间
 * @property string|null $real_ship_date 实际物流送出时间
 * @property int $status_id
 * @property int $payment_method_id
 * @property bool $is_paid
 * @property string|null $paid_at 支付时间
 * @property float $net_amount 需要支付的费用
 * @property float $paid_amount 已支付费用
 * @property float $payable_amount 待支付费用
 * @property string|null $ship_address
 * @property string|null $identification_number 物流标识符
 * @property string|null $location 仓库地址
 * @property float $discount 折扣
 * @property int $created_by
 * @property int|null $assigned_to
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property \Illuminate\Support\Carbon|null $deleted_at
 * @property-read \App\Models\User|null $assignedTo
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Attachment[] $attachments
 * @property-read int|null $attachments_count
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Order\OrderBundle[] $bundles
 * @property-read int|null $bundles_count
 * @property-read \App\Models\User $createdBy
 * @property-read \App\Models\Customer $customer
 * @property-read mixed $expect_duration
 * @property-read mixed $real_duration
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Order\OrderItem[] $items
 * @property-read int|null $items_count
 * @property-read \App\Models\Order\PaymentMethod $paymentMethod
 * @property-read \App\Models\Order\OrderStatus $status
 * @method static bool|null forceDelete()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order fuzzyFilter($queryString)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order newQuery()
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Order\Order onlyTrashed()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order query()
 * @method static bool|null restore()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereAssignedTo($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereCreatedBy($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereCustomerId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereDeletedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereDescription($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereDiscount($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereExpectedRentalOutDate($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereExpectedReturnDate($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereExpectedShipDate($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereIdentificationNumber($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereIsPaid($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereLocation($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereNetAmount($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereOrderNumber($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order wherePaidAmount($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order wherePaidAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order wherePayableAmount($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order wherePaymentMethodId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereRealRentalOutDate($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereRealReturnDate($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereRealShipDate($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereShipAddress($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereStatusId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Order\Order whereUpdatedAt($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Order\Order withTrashed()
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Order\Order withoutTrashed()
 * @mixin \Eloquent
 */
class Order extends Model
{
    use SoftDeletes, UsesTenantConnection;
    protected $guarded = [];
    protected $with = ['customer', 'status', 'paymentMethod', 'createdBy', 'assignedTo'];

    public function getExpectDurationAttribute()
    {
        $startAt = $this->attributes["expected_rental_out_date"];
        $endAt = $this->attributes["expected_return_date"];
        if (!empty($startAt) && !empty($endAt)) {
            $begin = Carbon::createFromFormat(config("app.date_format"), $startAt);
            $end = Carbon::createFromFormat(config("app.date_format"), $endAt);
            return $begin->diffInDays($end);
        }
        return null;
    }

    public function getRealDurationAttribute()
    {
        $startAt = $this->attributes["real_rental_out_date"];
        $endAt = $this->attributes["real_return_date"];
        if (!empty($startAt) && !empty($endAt)) {
            $begin = Carbon::createFromFormat(config("app.date_format"), $startAt);
            $end = Carbon::createFromFormat(config("app.date_format"), $endAt);
            return $begin->diffInDays($end);
        }
        return null;
    }

    public function scopeFuzzyFilter($query, $queryString)
    {
        $likeStr = '%' . $queryString . '%';
        $customerIds = Customer::where("name", 'like', $likeStr)->select(['id'])->get()->pluck(['id']);
        $statusId = OrderStatus::where("name", 'like', $likeStr)->select(['id'])->get()->pluck(['id']);

        $query->where('order_number', 'like', $likeStr)
            ->orWhere('ship_address', 'like', $likeStr)
            ->orWhere('identification_number', 'like', $likeStr)
            ->orWhereIn('status_id', $customerIds)
            ->orWhereIn('customer_id', $customerIds);
        try {
            if (Carbon::createFromFormat(config("app.date_format"), $queryString) != false) {
                $query->orWhere('expected_rental_out_date', $queryString);
                $query->orWhere('real_rental_out_date', $queryString);
                $query->orWhere('expected_return_date', $queryString);
                $query->orWhere('real_return_date', $queryString);
                $query->orWhere('expected_ship_date', $queryString);
                $query->orWhere('real_ship_date', $queryString);
                $query->orWhere('paid_at', $queryString);
                $query->orWhere('expected_ship_date', $queryString);
            }
        } catch (\Exception $e) {
        }
        return $query;
    }

    public function status()
    {
        return $this->belongsTo(OrderStatus::class, 'status_id');
    }

    public function paymentMethod()
    {
        return $this->belongsTo(PaymentMethod::class, 'payment_method_id');
    }

    public function createdBy()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function customer()
    {
        return $this->belongsTo(Customer::class, 'customer_id');
    }

    public function assignedTo()
    {
        return $this->belongsTo(User::class, 'assigned_to');
    }

    public function attachments()
    {
        return $this->morphMany(Attachment::class, 'attachable');
    }

    public function items()
    {
        return $this->hasMany(OrderItem::class);
    }

    public function bundles()
    {
        return $this->hasMany(OrderBundle::class);
    }
}
